<?php

namespace App\V3\V3_2_6\Services;

use App\Services\CommonService;
use App\Services\MessageService;
use App\V3\V3_2_6\Models\HcMaterielTypeModel;
use App\V3\V3_2_6\Models\LogInStorageModel;
use App\V3\V3_2_6\Models\MaterielClassModel;
use App\V3\V3_2_6\Models\MaterielProductContentModel;
use App\V3\V3_2_6\Models\MaterielsTypeModel;
use App\V3\V3_2_6\Models\MaterielTypeModel;
use App\V3\V3_2_6\Models\SellGoodsDetailModel;
use App\V3\V3_2_6\Models\SellModel;
use App\V3\V3_2_6\Models\SerialNumberModel;
use App\V3\V3_2_6\Models\StorageBatchModel;
use App\V3\V3_2_6\Models\StorageManageModel;
use App\V3\V3_2_6\Models\StorageModel;
use App\V3\V3_2_6\Models\StorageShelfLocationModel;
use App\V3\V3_2_6\Models\StorageShelfModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use OSS\OssClient;

class MaterielTypeService
{
    /**
     * 新建商品信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:43
     * @return array
     */
    static public function add($data, $time, $isUseShelf)
    {
        DB::beginTransaction();
        try {
            unset($data['price_type']);
            $shelfId = $data['shelf_id'];
            $locationId = $data['location_id'];

            $addType = $data['add_type'];

            $storageId = $data['storage_id'];
            $batchTitle = $data['batch_title'];
            $userId = $data['user_id'];
            $labelId = $data['label_id'];
            $inStorageTime = $data['in_storage_time'];
            $inStorageNum = !empty($data['in_storage_num'])?$data['in_storage_num']:0;

//            if(empty($data['serial_info'])) {
                $serialInfo = $data['serial_info'];
//            }

            $labelName = $data['label_name'];

            unset($data['storage_id']);

            unset($data['in_storage_time']);
            unset($data['product_content']);
            unset($data['label_name']);
            unset($data['in_storage_num']);
            unset($data['batch_title']);
            unset($data['user_id']);
            unset($data['serial_info']);
            unset($data['add_type']);
            unset($data['shelf_id']);
            unset($data['location_id']);
            unset($data['label_id']);

            if(!empty($data['materiel_img'])) {
                $materielImg = $data['materiel_img'];
                $materielImgGroup = array_filter(explode(',', $data['materiel_img']), function($v) { return $v !== ''; });

                $data['materiel_img'] = $materielImgGroup[0];
                $data['materiel_img_group'] = $materielImg;
            }

            $materielTypeId = MaterielsTypeModel::insertGetId($data);
            $result = ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielTypeId]];

            if($addType) {
                $data['storage_id'] = $storageId;
                $data['batch_title'] = $batchTitle;
                $data['user_id'] = $userId;
                $data['in_storage_time'] = $inStorageTime;
                $data['in_storage_num'] = $inStorageNum;
                $data['serial_info'] = $serialInfo;
                $data['shelf_id'] = $shelfId;
                $data['location_id'] = $locationId;
                $data['label_name'] = $labelName;
                $data['label_id'] = $labelId;
                self::createStorageManageInfo(0, $materielTypeId, $data, $time);
            }

            DB::commit();
            return $result;
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('新建商品-普通商品异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * 校验物料商品编号是否存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:35
     * @return bool
     */
    static public function checkNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeRandCode($data);

        if(!empty($checkMaterielNo)) {
            return false;
        }
        else {
            return true;
        }
    }

    static public function checkRandNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeCode($data);

        if(!empty($checkMaterielNo)) {
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * 验证商品信息是否已存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:41
     * @return bool
     */
    static public function checkMaterielInfo($data)
    {
        $checkMaterielInfo = MaterielsTypeModel::checkMaterielInfo($data);
        if(!empty($checkMaterielInfo)) {
            return false;
        }
        else {
            return true;
        }
    }

    //根据id检索商品信息是否已存在
    static public function checkMateriel($mainId, $id)
    {
        if(empty(MaterielsTypeModel::where(['id' => $id, 'main_id' => $mainId])->first()))
        {
            return false;
        }
        else {
            return true;
        }
    }

    //检查除自身外是否有相同的商品信息
    static public function checkMaterielInfoExceptself($data)
    {
        $checkMaterielTypeInfo = MaterielsTypeModel::where([
            'main_id' => $data['main_id'],
            'materiel_name' => $data['materiel_name'],
            'type_name' => $data['type_name'],
            'materiel_no' => $data['materiel_no'],
            'materiel_class_id' => $data['materiel_class_id'],
            'delete_flag' => 0,
        ])
            ->where('id', '!=', $data['id'])
            ->first();

        if(!empty($checkMaterielTypeInfo)) {
            return false;
        }
        else {
            return true;
        }
    }

    //获取指定商品详细信息
    static public function info($id)
    {
        $info = MaterielTypeModel::info($id);

        if(!empty($info['materiel_img_group'])) {
            $materielImgGroup = array_filter(explode(',',$info['materiel_img_group']), function($v) { return $v !== ''; });
            $specImg = array_filter(explode(',',$info['spec_img']), function($v) { return $v !== ''; });

            $info['spec_img'] = $specImg;
            $info['materiel_img_group'] = $materielImgGroup;
        }
        else {
            $info['materiel_img'] = $info['materiel_img']??'';
            $info['spec_img'] = [];
            $info['materiel_img_group'] = [];
        }

        return $info;
    }

    //物料列表
    static public function materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel)
    {
        $info = MaterielsTypeModel::materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel);

        foreach($info as &$value) {
            if(!empty($value['materiel_img'])) {
                $materielImg = array_filter(explode(',', $value['materiel_img']), function($v) { return $v !== ''; });

                $value['materiel_img'] = $materielImg[0];
            }


            if($value['is_product_materiel']) {
                $value['content_type_id'] = MaterielProductContentModel::where([
                    'product_id' => $value['id']
                ])
                    ->pluck('type_id')->toArray();
            }
            else {
                $value['content_type_id'] = [];
            }
        }

        return $info;
    }

    //物料列表-含库存信息

    static public function list($user, $data)
    {
        $condition = [];
        if(!empty($data['materiel_class_id'])) {
            $condition['a.materiel_class_id'] = ['EQ' => $data['materiel_class_id']];
        }

        if(isset($data['is_product_class'])) {
            $condition['c.is_product_class'] = ['EQ' => $data['is_product_class']];
        }

        if(isset($data['is_product_materiel'])) {
            $condition['b.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        $keyword = empty($data['keyword'])?'':$data['keyword'];


        $typeId = [];
        if(!empty($data['type_id'])) {
            $typeId = array_filter(explode(',', $data['type_id']));
        }

        $info = MaterielsTypeModel::getMaterielTypeList($user, $condition, $keyword, $data, $typeId);

        if($data['user_type']) {
            $storageInfo = StorageModel::getSelfStorageInfo([
                'user_id' => $data['user_id'],
                'delete_flag' => 0
            ]);


            foreach($info as $key => &$value) {
                if(!empty($value['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $value['materiel_img']), function($v) { return $v !== ''; });

                    $value['materiel_img'] = $materielImg[0];
                }

                if(!$data['is_share_storage_operate']) {
                    if (!in_array($value['storage_id'], $storageInfo)) {
                        unset($info[$key]);
                    }
                }
            }
        }
        else {
            foreach($info as $key => &$value) {
                if(!empty($value['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $value['materiel_img']), function($v) { return $v !== ''; });

                    $value['materiel_img'] = $materielImg[0];
                }
            }
        }

        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($info), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        return [
            'total' => count($info),
            'current_page' => $currentPage,
            'next_page_url' => count($result) < $data['pageSize']?null:config('app.url')."storage_manage_list?=".($data['currentPage']+1),
            'prev_page_url' => $currentPage==1?null:config('app.url')."storage_manage_list?=".($currentPage-1),
            "path" => config('app.url')."storage_manage_list",
            "to" => $currentPage * $data['pageSize'],
            'data' => $result,
            "per_page" => $data['pageSize']
        ];

        return array_values($info);
    }

    //修改成本价
    static public function editMaterielCost($data)
    {
        DB::beginTransaction();

        try {
            MaterielsTypeModel::where('id', $data['id'])->update(['cost' => $data['cost']]);
            StorageManageModel::where('type_id', $data['id'])->update(['materiel_mean_cost' => $data['cost']]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('修改成本异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //新建套件
    public static function addProductMateriel(array $data, $time, $isUseShelf)
    {
        $classInfo = MaterielClassModel::getProductClassInfo($data);

        if(empty($classInfo)) {
            return ['code' => 1, 'msg' => '商品类型与套件不匹配，请重试', 'data' => ''];
        }

        $productContent = [];
        if(!empty($data['product_content'])) {
            $productContent = json_decode($data['product_content'], true);
        }

        DB::beginTransaction();

        try {
            $addType = $data['add_type'];
            $priceType = $data['price_type'];

//            if(!empty($data['storage_id'])) {
                $storageId = $data['storage_id'];
//            }
            $batchTitle = $data['batch_title'];
            $labelName = $data['label_name'];
            $userId = $data['user_id'];
            $labelId = $data['label_id'];
            $inStorageTime = $data['in_storage_time'];
            $inStorageNum = !empty($data['in_storage_num'])?$data['in_storage_num']:0;
//            if(!empty($data['serial_info'])) {
                $serialInfo = $data['serial_info'];
//            }

//            if(!empty($data['shelf_id'])) {
                $shelfId = $data['shelf_id'];
//            }
//
//            if(!empty($data['location_id'])) {
                $locationId = $data['location_id'];
//            }

            unset($data['price_type']);
            unset($data['in_storage_time']);
            unset($data['label_name']);
            unset($data['product_content']);
            unset($data['product_content']);
            unset($data['in_storage_num']);
            unset($data['batch_title']);
            unset($data['user_id']);
            unset($data['serial_info']);
            unset($data['storage_id']);
            unset($data['add_type']);
            unset($data['shelf_id']);
            unset($data['location_id']);
            unset($data['label_id']);

            if(!empty($data['materiel_img'])) {
                $materielImg = $data['materiel_img'];
                $materielImgGroup = array_filter(explode(',', $data['materiel_img']), function($v) { return $v !== ''; });

                $data['materiel_img'] = $materielImgGroup[0];
                $data['materiel_img_group'] = $materielImg;
            }

            $materielTypeId = MaterielsTypeModel::insertGetId($data);;

            if(!empty($productContent)) {
                $arr = [];
                $sellPrice = 0;//原商品售价
                $price = 0;//改价后金额
                $hasSerialMateriel = 0;
                foreach($productContent as $value) {
                    if(!isset($value['type_id']) || empty($value['type_id'])) {
                        throw new Exception('请选择要添加的商品');
                    }

                    $materielTypeInfo = MaterielsTypeModel::info($value['type_id']);

                    if(empty($materielTypeInfo)) {
                        throw new Exception('商品信息不存在,请重新套餐组件后添加');
                    }

                    if($materielTypeInfo['delete_flag']) {
                        throw new Exception('商品:'.$materielTypeInfo['materiel_name'].'已被删除，无法添加到套餐中');
                    }

                    if($value['num'] <= 0) {
                        return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                    }

                    if(!is_numeric($value['num'])) {
                        return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                    }

                    if($value['price'] < 0) {
                        return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                    }

                    if(!is_numeric($value['price'])) {
                        return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                    }

                    $price += $value['price'] * $value['num'];
                    $sellPrice += $value['selling_price'] * $value['num'];

                    $materielInfo = MaterielTypeModel::where('id', $value['type_id'])->first();

                    if($materielInfo['is_use_serial']) {
                        $hasSerialMateriel = 1;
                    }
                }

                $totalPrice = 0;
                $isUp = 0;
                $discount = 0;
                $calcRatio = 0;
                if($priceType) {
                    foreach($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        //是否溢价
                        if($data['selling_price'] > $price) {
                            $isUp = 1;

                            if($price == 0) {
                                $discount = 0;
                                $calcRatio = 0;
                            }
                            else {
                                $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                                $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                            }

                            $newPrice = ($val['price'] * $discount) + $val['price'];
                        }
                        else {
                            $isUp = 0;
                            if($sellPrice == 0) {
                                $discount = 0;
                            }
                            else {
                                $discount = substr(($price / $sellPrice), 0, 4);
                            }

                            $newPrice = $val['price'] * $discount;

                            if($price == 0) {
                                $calcRatio = 0;
                            }
                            else {
                                $calcRatio = sprintf('%.2f', ($sellPrice / $price));
                            }
                        }

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $newPrice),
                            'origin_price' => $val['selling_price'],
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                            'product_id' => $materielTypeId,
                            'num' => $val['num'],
                            'created_at' => $data['created_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));
                    }

                    MaterielsTypeModel::where('id', $materielTypeId)
                        ->update([
                            'selling_price' => $data['selling_price'],
                            'ratio' => $discount,
                            'price_up_or_down' => $isUp,
                            'calc_ratio' => $calcRatio,
                        ]);
                }
                else {
                    foreach($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $val['price']),
                            'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                            'origin_price' => $val['selling_price'],
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'product_id' => $materielTypeId,
                            'num' => $val['num'],
                            'created_at' => $data['created_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));
                    }

                    MaterielsTypeModel::where('id', $materielTypeId)
                        ->update(['selling_price' => $price]);
                }

                MaterielProductContentModel::insert($arr);

                if($priceType) {
                    $balance = $data['selling_price'] - $totalPrice;

                    $firstData = MaterielProductContentModel::where('product_id', $materielTypeId)
                        ->first();

                    MaterielProductContentModel::where('id', $firstData['id'])
                        ->update([
                            'price' => DB::raw('price +' . ($balance / 10)),
                            'total_price' => DB::raw('total_price +' . $balance)
                        ]);
                }

                //若套件为存在开启了序列号的商品，则套餐标记为必须开启序列号
                MaterielTypeModel::where('id', $materielTypeId)
                    ->update(['is_use_serial' => $hasSerialMateriel]);
            }

            if($addType) {
                $data['storage_id'] = $storageId;
                $data['batch_title'] = $batchTitle;
                $data['user_id'] = $userId;
                $data['in_storage_time'] = $inStorageTime;
                $data['in_storage_num'] = $inStorageNum;
                $data['serial_info'] = $serialInfo;
                $data['product_content'] = $productContent;
                $data['shelf_id'] = $shelfId;
                $data['location_id'] = $locationId;
                $data['label_id'] = $labelId;
                $data['label_name'] = $labelName;

                self::createStorageManageInfo(1, $materielTypeId, $data, $time);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielTypeId]];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('添加套件异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    public static function editMateriel(array $data,int $userId)
    {
        unset($data['product_content']);
        unset($data['price_type']);
        unset($data['is_product_materiel']);
        DB::beginTransaction();

        try {
            //检查物料商品编号是否存在
//            $checkNo = MaterielTypeService::checkRandNo($data);
//            if(!$checkNo) {
//                return ['code' => 1, 'msg' => '商品编号已存在，请重新输入', 'data' => ''];
//            }

            //验证商品信息除己身外是否已存在
            $checkMaterielInfo = MaterielTypeService::checkMaterielInfoExceptself($data);

            if(!$checkMaterielInfo) {
                return ['code' => 1, 'msg' => '物料类型`'.$data['materiel_name'].'-'.$data['type_name'].'`已存在', 'data' => ''];
            }

            $materielTypeInfo = MaterielsTypeModel::where('id', $data['id'])->first();
            if(!empty($materielTypeInfo['materiel_img'])) {
                $client = new OssClient(
                    config('app.aliyun_oss_key'),
                    config('app.aliyun_oss_secret'),
                    config('app.aliyun_oss_endpoint'),
                );

                $isHttpStart = substr($materielTypeInfo['materiel_img'], 0, 4);

                if($isHttpStart != 'http') {
                    if(file_exists(public_path().$materielTypeInfo['materiel_img'])) {
                        unlink(public_path().$materielTypeInfo['materiel_img']);
                    }
                }
                else {
                    $substrUrl = explode('uploads', $materielTypeInfo['materiel_img']);

                    $client->deleteObject(config('app.aliyun_oss_bucket'), 'uploads'.$substrUrl[1]);
                }
            }

            if(!empty($data['materiel_img'])) {
                $materielImg = $data['materiel_img'];
                $materielImgGroup = array_filter(explode(',', $data['materiel_img']), function($v) { return $v !== ''; });

                $data['materiel_img'] = $materielImgGroup[0];
                $data['materiel_img_group'] = $materielImg;
            }

            MaterielsTypeModel::where('id', $data['id'])->update($data);

            $storageManageInfo = StorageManageModel::where('type_id', $data['id'])->where('delete_flag', 0)->first();
            if(!empty($storageManageInfo)) {
                StorageManageModel::where([
                    'type_id' => $data['id'],
                    'delete_flag' => 0
                ])
                    ->update([
                        'materiel_name' => $data['materiel_name'],
                        'type_name' => $data['type_name'],
                        'materiel_mean_cost' => $data['cost'],
                        'materiel_no' => $data['materiel_no'],
                    ]);
//                $storageManageInfo->materiel_name = $data['materiel_name'];
//                $storageManageInfo->type_name = $data['type_name'];
//                $storageManageInfo->materiel_no = $data['materiel_no'];
//                $storageManageInfo->materiel_mean_cost = $data['cost'];
//                $storageManageInfo->save();
            }

//            unset($data['materiel_thumbnail_img']);

            // HcMaterielTypeModel::where(['id'=>$data['id'],'main_id'=>$data['main_id']])->update($data);
//            StorageManageModel::where('type_id', $data['id'])->update([
//                'materiel_mean_cost' => $data['cost']
//            ]);
            CommonService::operateResult($userId,$materielTypeInfo,$data['updated_at']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('编辑商品信息异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    public static function editProductMateriel(array $data,int $userId)
    {
        $newData = $data;
        unset($newData['product_content']);

        $priceType = $data['price_type'];
        unset($data['price_type']);

        $productContent = json_decode($data['product_content'], true);

        $info = MaterielTypeModel::where('id', $data['id'])->first();

        if($info['product_use_tag']) {
             return ['code' => 1, 'msg' => '目标套餐商品已被使用，无法进行编辑', 'data' => ''];
         }

        self::editMateriel($newData,$userId);
        if($info['product_use_tag']) {
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }else{
            try {
                MaterielProductContentModel::where('product_id', $data['id'])->delete();

                $sellPrice = 0;
                $price = 0;
                $arr = [];
                foreach($productContent as $value) {
                    if(!isset($value['type_id']) || empty($value['type_id'])) {
                        return ['code' => 1, 'msg' => '请选择要添加的商品', 'data' => ''];
                    }

                    if($value['num'] <= 0) {
                        return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                    }

                    if(!is_numeric($value['num'])) {
                        return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                    }

                    if($value['price'] < 0) {
                        return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                    }

                    if(!is_numeric($value['price'])) {
                        return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                    }

                    $sellPrice += $value['selling_price'] * $value['num'];
                    $price += $value['price'] * $value['num'];
                }

                $totalPrice = 0;
                $isUp = 0;
                $discount = 0;
                $calcRatio = 0;
                $hasSerialMateriel = 0;
                if($priceType) {
                    foreach($productContent as $val) {
                        if($data['selling_price'] > $price) {
                            $isUp = 1;
                            $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                            $newPrice = ($val['price'] * $discount) + $val['price'];
                            $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                        }
                        else {
                            $discount = substr(($price / $sellPrice), 0, 4);
                            $newPrice = $val['price'] * $discount;
                            $calcRatio = $sellPrice / $price;
                            $calcRatio = sprintf('%.2f', ($sellPrice / $price));
                        }

                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $newPrice),
                            'origin_price' => ($val['selling_price']),
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                            'product_id' => $data['id'],
                            'num' => $val['num'],
                            'created_at' => $data['updated_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));

                        if($typeInfo['is_use_serial']) {
                            $hasSerialMateriel = 1;
                        }
                    }

                    MaterielsTypeModel::where('id', $data['id'])
                        ->update([
                            'selling_price' => $data['selling_price'],
                            'ratio' => $discount,
                            'price_up_or_down' => $isUp,
                            'calc_ratio' => $calcRatio,
                            'is_use_serial' => $hasSerialMateriel
                        ]);
                }
                else {
                    foreach($productContent as $val) {
                        $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                        $arr[] = [
                            'main_id' => $data['main_id'],
                            'type_id' => $val['type_id'],
                            'price' => sprintf('%.6f', $val['price']),
                            'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                            'origin_price' => ($val['selling_price']),
                            'is_use_serial' => $typeInfo['is_use_serial'],
                            'product_id' => $data['id'],
                            'num' => $val['num'],
                            'created_at' => $data['updated_at']
                        ];

                        $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));

                        if($typeInfo['is_use_serial']) {
                            $hasSerialMateriel = 1;
                        }
                    }

                    MaterielsTypeModel::where('id', $data['id'])
                        ->update([
                            'selling_price' => $price,
                            'is_use_serial' => $hasSerialMateriel
                        ]);
                }

                MaterielProductContentModel::insert($arr);

                if($priceType) {
                    $balance = $data['selling_price'] - $totalPrice;

                    $firstData = MaterielProductContentModel::where('product_id', $data['id'])
                        ->first();

                    MaterielProductContentModel::where('id', $firstData['id'])
                        ->update([
                            'price' => DB::raw('price +' . ($balance / 10)),
                            'total_price' => DB::raw('total_price +' . $balance)
                        ]);
                }
                CommonService::operateResult($userId,$productContent,$data['updated_at']);
                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            }
            catch(Exception $e) {
                DB::rollBack();
                Log::debug('编辑套件异常:'.var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => '编辑套件信息异常', 'data' => ''];
            }
        }
    }

    public static function packageInfo(array $data)
    {
        $materielProductContentInfo = MaterielProductContentModel::select(
            'a.*',
            'materiel_name',
            'type_name',
            'materiel_unit',
            'materiel_img'
        )
            ->where([
                'product_id' => $data['id']
            ])
            ->from('materiel_product_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->get()->toArray();

        if(!empty($data['sell_id'])) {
            $sellInfo = SellGoodsDetailModel::where([
                'sell_id' => $data['sell_id'],
                'materiel_type_id' => $data['id'],
                'is_product_materiel' => 1
            ])->first();

            if(empty($sellInfo)) {
                return ['code' => 1, 'msg' => '类型错误，暂无内容', 'data' => ''];
            }

            $price = 0;
            $totalPrice = 0;
            foreach($materielProductContentInfo as &$value) {
                $value['price'] = $value['price'] * $sellInfo['calc_ratio'];
                $value['total_price'] = $value['total_price'] * $sellInfo['calc_ratio'];

                $price += $value['price'];
                $totalPrice += $value['total_price'];
            }

            if($sellInfo['price'] > $totalPrice) {//补足
                $balance = $sellInfo['price'] - $totalPrice;

                $materielProductContentInfo[0]['price'] += $balance;
                $materielProductContentInfo[0]['total_price'] += $balance;
            }
            else {//抵扣
                $balance = $totalPrice - $sellInfo['price'];

                //对套件按价格降序排列
                usort($materielProductContentInfo, function($a, $b) {
                    if($a['price'] == $b['price']) {
                        return 0;
                    }

                    return ($a['price'] > $b['price'])?-1:1;
                });

                $materielProductContentInfo[0]['price'] -= $balance;
                $materielProductContentInfo[0]['total_price'] -= $balance;
            }
        }

        foreach($materielProductContentInfo as &$val) {
            if(!empty($val['materiel_img'])) {
                $materielImg = array_filter(explode(',', $val['materiel_img']), function($v) { return $v !== ''; });

                $val['materiel_img'] = $materielImg[0];
            }
        }

        return $materielProductContentInfo;
    }

    public static function updateProductInfo(array $data)
    {
        DB::beginTransaction();

        try {
            if(!$data['is_product_materiel']) {
                //获取目标商品相关的所有套餐信息
                $productContentInfo = MaterielProductContentModel::where('type_id', $data['id'])->get()->toArray();

                if(!empty($productContentInfo)) {
                    //更新目标商品在套餐商品表中的序列号开启状态
                    MaterielProductContentModel::where('type_id', $data['id'])->update(['is_use_serial' => $data['is_use_serial']]);

                    $productId = [];
                    foreach($productContentInfo as $contentVal) {
                        $productId[] = $contentVal['product_id'];
                    }

                    if(!empty($productId)) {
                        $productId = array_unique($productId);
                        //检查已使用目标商品的套餐是否仍存在使用已开启序列号商品的情况
                        $checkProductInfo = MaterielProductContentModel::where('is_use_serial', 1)
                            ->whereIn('product_id', $productId)->get()->toArray();

                        if(empty($checkProductInfo)) {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 0]);
                        }
                        else {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 1]);
                        }
                    }
                }
            }

            DB::commit();
            return true;
        }
        catch(Exception $e) {
            DB::rollBack();
            return ['code' => 1, 'msg' => '编辑商品信息失败，请重试', 'data' => ''];
        }
    }

    public static function goodsInfo($data){
        return MaterielTypeModel::where(['id'=>$data['id'],'delete_flag'=>0])->first();
    }

    //新建商品侧入库公共方法
    private static function createStorageManageInfo($type, $materielTypeId, $data, $time)
    {
        $data['in_storage_num'] = $data['in_storage_num']??0;

        if($data['in_storage_num'] < 0) {
            throw new Exception('入库数量必须大于等于0');
        }

        $storageInfo = StorageModel::getStorageDetail($data['storage_id']);

        if(empty($storageInfo)) {
            throw new Exception('入库的目标仓库不存在，无法完成入库,请检查后重试');
        }

        $result = self::goodsInStorage($materielTypeId, $data, $time);

//        switch($type) {
//            case 0://新建商品入库
//                $result = self::goodsInStorage($materielTypeId, $data, $time);
//                break;
//            case 1://新建套餐入库
//                $result = self::productInStorage($materielTypeId, $data, $time);
//                break;
//        }

        return $result;
    }

    //新建套餐侧入库
    private static function productInStorage($materielTypeId, $data, $time)
    {
        $productContent = $data['product_content'];

        $storageManageInfo = self::materielAddInStorage($materielTypeId, $data, $time, 1);

        if(!empty($productContent)) {
            //逻辑处理开始
            $serialInfo = '';
            $serialArr = [];
            $getInstorageNum = [];
            foreach($productContent as $value) {
                //获取套餐内组件商品所需总数
                $productContentNum = $data['in_storage_num'] * $value['num'];

                //获取组件商品信息
                $materielTypeInfo = MaterielsTypeModel::getMaterielInfo($value['type_id']);

                //商品是否开启序列号;0:否;1:是;
                if($materielTypeInfo['is_use_serial']) {
                    //序列号未填写
//                    if(empty($value['serial_info'])) {
//                        throw new Exception('组件商品:'.
//                            $materielTypeInfo['materiel_name'].'已开启序列号，请填写后重试');
//                    }

                    $serialInfo .= $value['serial_info'].',';

                    $serialData = array_unique(array_filter(explode(',', $data['serial_info']), function($v) { return $v !== ''; }));

                    if(!is_integer(count($serialData) / $value['num'])) {
                        throw new Exception('组件商品:'.$materielTypeInfo['materiel_name'].'填写的序列号与实际入库数量不匹配');
                    }

                    $getInstorageNum[] = count($serialData) / $value['num'];

                    foreach($serialData as $val) {
                        //检查组件商品序列号信息
                        $checkSerialInfo = SerialNumberModel::where([
                            'serial_no' => $val,
                            'goods_id' => $value['type_id'],
                            'main_id' => $data['main_id']
                        ])->first();

                        if(!empty($checkSerialInfo)) {
                            throw new Exception('组件商品:'.$materielTypeInfo['materiel_name'].'的序列号:'.$val.'已存在，无法重复添加');
                        }

                        //组装序列号数据
                        $serialArr[] = [
                            'storage_manage_id' => 0,
                            'package_storage_id' => $storageManageInfo['storage_manage_id'],
                            'batch_no' => $storageManageInfo['batch_no'],
                            'goods_id' => $value['type_id'],
                            'serial_no' => $val,
                            'package_id' => $materielTypeId,
                            'status' => 1,
                            'created_at' => $time,
                            'main_id' => $data['main_id']
                        ];
                    }
                }
            }

            if(!empty($getInstorageNum)) {
                if(count(array_unique($getInstorageNum)) > 1) {
                    throw new Exception('部分商品之间存在序列号数量和实际入库所需数量不匹配的情况，请检查后重新添加');
                }

                if($getInstorageNum[0] != $data['in_storage_num']) {
                    throw new Exception('部分商品添加的序列号数量与实际入库所需数量不匹配，请检查后重新添加');
                }
            }

            //插入序列号
            if(!empty($serialArr)) {
                SerialNumberModel::insert($serialArr);
            }

            //将被插入的序列号更新到入库记录中
            LogInStorageModel::where('id', $storageManageInfo['log_id'])->update(['serial_number' => substr($serialInfo, 0, -1)]);
        }

        return true;
    }

    //新建商品侧入库
    private static function goodsInStorage($materielTypeId, $data, $time): bool
    {
        $storageManageInfo = self::materielAddInStorage($materielTypeId, $data, $time, 0);

        $serialArr = [];
        $serialStr = '';

        if($data['is_use_serial']) {
            if(empty($data['serial_info'])) {
                throw new Exception('商品:'.
                    $data['materiel_name'].'已开启序列号，请填写后重试');
            }

            $serialStr = $data['serial_info'];

            $serialData = array_unique(array_filter(explode(',', $data['serial_info']), function($v) { return $v !== ''; }));

            //序列号数量少于商品数量
            if(count($serialData) < $data['in_storage_num']) {
                throw new Exception('组件商品:'.
                    $data['materiel_name'].'所需序列号数量X'.$data['in_storage_num'].
                    ',尚缺少X'.($data['in_storage_num'] - count($serialData)));
            }

            //序列号数量超出商品数量
            if(count($serialData) > $data['in_storage_num']) {
                throw new Exception('组件商品:'.
                    $data['materiel_name'].'所需序列号数量X'.$data['in_storage_num'].
                    ',超出X'.(count($serialData) - $data['in_storage_num']));
            }

            foreach($serialData as $val) {
                //组装序列号数据
                $serialArr[] = [
                    'storage_manage_id' => $storageManageInfo['storage_manage_id'],
                    'package_storage_id' => 0,
                    'batch_no' => $storageManageInfo['batch_no'],
                    'serial_no' => $val,
                    'goods_id' => $materielTypeId,
                    'package_id' => 0,
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'created_at' => $time
                ];
            }
        }

        if($serialStr != '') {
            LogInStorageModel::where('id', $storageManageInfo['log_id'])->update(['serial_number' => $serialStr]);
        }

        if(!empty($serialArr)) {
            SerialNumberModel::insert($serialArr);
        }

        return true;
    }

    //新建商品公共入库
    private static function materielAddInStorage($materielTypeId, $data, $time, $isProductMateriel = 0): array
    {
        //获取仓库信息
        $storageInfo = StorageModel::where(['id' => $data['storage_id']])->first();

        if(empty($data['location_id'])) {
            //获取货架信息
            $shelfInfo = StorageShelfModel::where([
                'storage_id'=> $data['storage_id'],
                'shelf_type'=>1
            ])->first();

            //获取库位信息
            $locationInfo = StorageShelfLocationModel::where([
                'main_id'=>$data['main_id'],
                'shelf_id'=>$shelfInfo['id'],
                'location_type'=>1
            ])->first();

            $data['location_id'] = $locationInfo['id'];
            $data['shelf_id'] = $shelfInfo['id'];
        }

        //商品信息
        $classInfo = MaterielClassModel::where(['id'=>$data['materiel_class_id']])->first();

        //入库商品信息
        $inStorageManageInfo = [
            'materiel_class_id' => $data['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $classInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => $classInfo['class_no'],//物料二级分类名称
            'type_id' => $materielTypeId,//物料id
            'materiel_name' => $data['materiel_name'],//物料名称
            'type_name' => $data['type_name'],//物料型号名称
            'materiel_no' => $data['materiel_no'],//物料编号
            'materiel_mean_cost' => $data['cost'],
            'storage_id' => $data['storage_id'],//仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'is_product_materiel' => $isProductMateriel,
            'in_storage_num' => $data['in_storage_num'],//入库数量
            'virtual_storage_num' => $data['in_storage_num'],
            'main_id' => $data['main_id'],//主账号id
            'in_storage_time' => $time,//入库时间
            'alert_num' => 0,
            'created_at' => $time,
            'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id']
        ];

        $storageManageId = StorageManageModel::insertGetId($inStorageManageInfo);

        //批次号生成
        $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
        $checkBatchNo = StorageBatchModel::where('main_id', $data['main_id'])
            ->where('batch_no', $batchNo)->first();

        do {
            $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
        }
        while(!empty($checkBatchNo));

        $batchId = MaterielService::createBatchInfoGetId(
            $batchNo,
            $storageManageId,
            $data['cost'],
            $data['in_storage_num'],
            0,
            $data['main_id']
        );

        //入库日志信息
        $logData = [
            'curr_storage_manage_id' => $storageManageId,
            'materiel_type_id' => $materielTypeId,//物料id
            'batch_id' => $batchId,//物料id
            'materiel_name' => $data['materiel_name'],//物料名称
            'type_name' => $data['type_name'],//物料型号
            'materiel_no' => $data['materiel_no'],//物料编号
            'materiel_class_id' => $data['materiel_class_id'],//物料二级分类主键名称
            'materiel_class_name' => $classInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => $classInfo['class_no'],//物料二级分类编号
            'type' => 2,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $data['storage_id'],//仓库主键id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'operate_num' => $data['in_storage_num'],//操作数量
            'last_storage_num' => 0,//操作前库存数
            'materiel_mean_cost' => $data['cost'],//物料均价
            'next_storage_num' => $data['in_storage_num'],//操作后库存数
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:退货;3:采购;
            'in_storage_time' => $time,//入库时间
            'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id'],
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人用户id
            'main_id' => $data['main_id'],//主账号id
            'remark' => empty($data['remark'])?'':$data['remark'],
            'label_id' => $data['label_id'],
            'label_name' => $data['label_name'],
            'created_at' => $time,
        ];

        $logId = LogInstorageModel::query()->insertGetId($logData);

//        MessageService::sendInSms(
//            time(),
//            $data['materiel_name'],
//            $data['type_name'],
//            $data['storage_id'],
//            $storageInfo['storage_name'],
//            $data,
//            $data['in_storage_num'],
//            $data['in_storage_num']
//        );

        return ['storage_manage_id' => $storageManageId, 'log_id' => $logId, 'batch_no' => $batchNo];
    }
}
